﻿using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Caliburn.Micro;
using DomusDotNet.Sbm.Client.SL4.WCFServices;
using System.ComponentModel.Composition;
using DomusDotNet.Sbm.Client.SL4.Services;

namespace DomusDotNet.Sbm.Client.SL4.Infrastructure
{
    public class WCFServiceCallResult: IResult
    {

        [Import]
        public ISharedBookshelfService Service { get; set; }
		[Import]
		public ISecurityContext SecurityContext { get; set; }

        public WCFServiceCallResult(object request) {
            this.Request = request;
        }

        public object Request { get; private set; }
        public object Response { get; set; }
        
        public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };

        public void Execute(ActionExecutionContext context)
        {
			var authenticatedRequest = this.Request as AuthenticatedRequestBase;
			var identity = SecurityContext.CurrentUser.Identity as IIdentityWithToken;
			if (authenticatedRequest != null && identity != null)
				authenticatedRequest.SessionGUID = identity.LoginToken.ToString();

            CallServiceAsync(this.Request,
                response =>
                {
                    this.Response = response;
                    Completed(this, new ResultCompletionEventArgs());
                },
                ex => {
                    Completed(this, new ResultCompletionEventArgs { Error = ex});
                }
            );
        }


        void CallServiceAsync(object request, Action<object> onResponseReceived, Action<Exception> onError) {
            
            var beginMethod = typeof(ISharedBookshelfService).GetMethods()
                .Where(m=>m.Name.StartsWith("Begin"))
                .Where(m=>m.GetParameters()[0].ParameterType.IsInstanceOfType(this.Request))
                .Single();

            var endMethod = typeof(ISharedBookshelfService).GetMethods()
                .Where(m => m.Name.Equals("End" + beginMethod.Name.Substring(5)))
                .Single();

            
            AsyncCallback callback = ar => {
                object response;
                try
                {
                    response = endMethod.Invoke(Service, new object[] { ar });
                    onResponseReceived(response);
                }
                catch(Exception ex) {
                    onError(ex);
                }
            };

            beginMethod.Invoke(Service, new object[] { this.Request, callback, null });
            
        }


        public T GetRequest<T>()
        {
            return (T)Request;
        }
        public T GetResponse<T>()
        {
            return (T)Response;
        }

    }
}
